home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
small_c.arc
/
CC.ARC
< prev
next >
Wrap
Text File
|
1985-09-14
|
79KB
|
3,147 lines
>>> STDIO.H 387
/*
** STDIO.H -- Standard Small-C Definitions
**
** Copyright 1983 L. E. Payne and J. E. Hendrix
*/
#define stdin 0
#define stdout 1
#define stderr 2
#define stdaux 3
#define stdprn 4
#define ERR (-2)
#define EOF (-1)
#define YES 1
#define NO 0
#define NULL 0
#define CR 13
#define LF 10
#define BELL 7
#define SPACE ' '
#define NEWLINE LF
>>> NOTICE.H 124
#define VERSION "Small-C Compiler, Version 2.1, (Rev. 70)\n"
#define CRIGHT1 "Copyright 1982, 1983, 1985 J. E. Hendrix\n\n"
>>> CC.DEF 5310
/*
** CC.DEF -- Symbol Definitions for Small-C compiler.
*/
/*
** compile options
*/
#define NOCCARGC /* no argument counts */
#define SEPARATE /* compile separately */
#define OPTIMIZE /* compile output optimizer */
#define DYNAMIC /* allocate memory dynamically */
#define COL /* terminate labels with a colon */
/* #define UPPER /* force symbols to upper case */
#define LINK /* will use with linking loader */
/*
** machine dependent parameters
*/
#define BPW 2 /* bytes per word */
#define LBPW 1 /* log2(BPW) */
#define SBPC 1 /* stack bytes per character */
#define ERRCODE 7 /* op sys return code */
/*
** symbol table format
*/
#define IDENT 0
#define TYPE 1
#define CLASS 2
#define OFFSET 3
#define NAME 5
#define OFFSIZE (NAME-OFFSET)
#define SYMAVG 10
#define SYMMAX 14
/*
** symbol table parameters
*/
#define NUMLOCS 25
#define STARTLOC symtab
#define ENDLOC (symtab+NUMLOCS*SYMAVG)
#define NUMGLBS 200
#define STARTGLB ENDLOC
#define ENDGLB (ENDLOC+(NUMGLBS-1)*SYMMAX)
#define SYMTBSZ 3050 /* (NUMLOCS*SYMAVG + NUMGLBS*SYMMAX) */
/*
** System wide name size (for symbols)
*/
#define NAMESIZE 9
#define NAMEMAX 8
/*
** possible entries for "IDENT"
*/
#define LABEL 0
#define VARIABLE 1
#define ARRAY 2
#define POINTER 3
#define FUNCTION 4
/*
** possible entries for "TYPE"
** low order 2 bits make type unique within length
** high order bits give length of object
*/
/* LABEL 0 */
#define CCHAR (1<<2)
#define CINT (BPW<<2)
/*
** possible entries for "CLASS"
*/
/* LABEL 0 */
#define STATIC 1
#define AUTOMATIC 2
#define EXTERNAL 3
#define AUTOEXT 4
#define GLOBAL 5
/*
** segment types
*/
#define DATASEG 1
#define CODESEG 2
/*
** "switch" table
*/
#define SWSIZ (2*BPW)
#define SWTABSZ (90*SWSIZ)
/*
** "while" statement queue
*/
#define WQTABSZ 30
#define WQSIZ 3
#define WQMAX (wq+WQTABSZ-WQSIZ)
/*
** entry offsets in while queue
*/
#define WQSP 0
#define WQLOOP 1
#define WQEXIT 2
/*
** literal pool
*/
#define LITABSZ 1500
#define LITMAX (LITABSZ-1)
/*
** input line
*/
#define LINEMAX 127
#define LINESIZE 128
/*
** entries in staging buffer
*/
#define STAGESIZE 200
/*
** macro (define) pool
*/
#define MACNBR 300
#define MACNSIZE (MACNBR*(NAMESIZE+2))
#define MACNEND (macn+MACNSIZE)
#define MACQSIZE (MACNBR*7)
#define MACMAX (MACQSIZE-1)
/*
** statement types
*/
#define STIF 1
#define STWHILE 2
#define STRETURN 3
#define STBREAK 4
#define STCONT 5
#define STASM 6
#define STEXPR 7
#define STDO 8 /* compile "do" logic */
#define STFOR 9 /* compile "for" logic */
#define STSWITCH 10 /* compile "switch/case/default" logic */
#define STCASE 11
#define STDEF 12
#define STGOTO 13 /* compile "goto" logic */
#define STLABEL 14
/*
** compiler-generated p-codes
*/
#define _LABEL 0
#define _RLAB 1
#define _GCHAR 2
#define _GINT 3
#define _LINT 4
#define _LCHAR 5
#define _GSTK 6
#define _SCHAR 7
#define _SINT 8
#define _PINT 9
#define _PCHAR 10
#define _MOVE 11
#define _SWAP 12
#define _OFFSET 13
#define _STRING 14
#define _IMMED 15
#define _IMMED2 16
#define _PUSH 17
#define _POP 18
#define _SWAPSTK 19
#define _SW 20
#define _CALL 21
#define _FUNC 22
#define _RET 23
#define _CALLSTK 24
#define _JUMP 25
#define _TESTJUMP 26
#define _DEFBYTE 27
#define _DEFWORD 28
#define _DEFLABEL 29
#define _MODSTK 30
#define _DBL 31
#define _DBL2 32
#define _ADD 33
#define _SUB 34
#define _MULT 35
#define _DIV 36
#define _MOD 37
#define _OR 38
#define _XOR 39
#define _AND 40
#define _LNEG 41
#define _ASR 42
#define _ASL 43
#define _NEG 44
#define _COM 45
#define _INC 46
#define _DEC 47
#define _EQ 48
#define _EQ0 49
#define _NE 50
#define _NE0 51
#define _LT 52
#define _LT0 53
#define _LE 54
#define _LE0 55
#define _GT 56
#define _GT0 57
#define _GE 58
#define _GE0 59
#define _ULT 60
#define _ULT0 61
#define _ULE 62
#define _UGT 63
#define _UGE 64
#define _COUNT 65
#define _DB 66
#define _DBZERO 67
#define _DW 68
#define _DWZERO 69
/*
** optimizer-generated p-codes
*/
#define _ANY -1
#define _FINT 100 /* fetch local int */
#define _FCHAR 101 /* fetch local char */
#define _GLIO 102 /* get local int with offset */
#define _GLCO 103 /* get local char with offset */
#define _GGIO1 104 /* get global int with offset */
#define _GGIO2 105 /* continuation of _GGIO1 */
#define _GGCO1 106 /* get global char with offset */
#define _GGCO2 107 /* continuation OF _GGCO1 */
#define _ADDI 108 /* add immediate */
#define _SUBI 109 /* subtract immediate */
#define _INT_I 110 /* indirect integer post incr */
#define _INT_D 111 /* indirect integer post decr */
#define _CHAR_I 112 /* indirect character post incr */
#define _CHAR_D 113 /* indirect character post decr */
#define _XXX_I1 114 /* direct int/char post incr */
#define _XXX_D1 115 /* direct int/char post decr */
#define _XXX_X2 116 /* continue _XXX_I1 and _XXX_D1 */
>>> CC1.C 3548
/*
** Small-C Compiler Part 1
*/
#include <stdio.h>
#include "notice.h"
#include "cc.def"
/*
** miscellaneous storage
*/
int
#ifdef STGOTO
nogo, /* > 0 disables goto statements */
noloc, /* > 0 disables block locals */
#endif
op[16], /* function addresses of binary operators */
op2[16], /* same for unsigned operators */
opindex, /* index to matched operator */
opsize, /* size of operator in bytes */
swactive, /* true inside a switch */
swdefault,/* default label #, else 0 */
*swnext, /* address of next entry */
*swend, /* address of last table entry */
#ifdef DYNAMIC
*stage, /* output staging buffer */
*wq, /* while queue */
#else
stage[STAGESIZE*2],
wq[WQTABSZ],
#endif
argcs, /* static argc */
*argvs, /* static argv */
*wqptr, /* ptr to next entry */
litptr, /* ptr to next entry */
macptr, /* macro buffer index */
pptr, /* ptr to parsing buffer */
oper, /* address of binary operator function */
ch, /* current character of line being scanned */
nch, /* next character of line being scanned */
declared, /* # of local bytes declared, else -1 when done */
iflevel, /* #if... nest level */
skiplevel,/* level at which #if... skipping started */
func1, /* true for first function */
nxtlab, /* next avail label # */
litlab, /* label # assigned to literal pool */
beglab, /* beginning label -- first function */
csp, /* compiler relative stk ptr */
argstk, /* function arg sp */
argtop,
ncmp, /* # open compound statements */
errflag, /* non-zero after 1st error in statement */
eof, /* set non-zero on final input eof */
input, /* fd # for input file */
input2, /* fd # for "include" file */
output, /* fd # for output file */
files, /* non-zero if file list specified on cmd line */
filearg, /* cur file arg index */
glbflag, /* non-zero if internal globals */
ctext, /* non-zero to intermix c-source */
ccode, /* non-zero while parsing c-code */
/* zero when passing assembly code */
*stagenext,/* next addr in stage */
*stagetail,/* last addr of data in stage */
*stagelast,/* last addr in stage */
listfp, /* file pointer to list device */
lastst, /* last executed statement type */
*iptr, /* work ptr to any int buffer */
oldseg; /* current segment, 0, DATASEG, CODESEG */
char
#ifdef OPTIMIZE
optimize, /* optimize output of staging buffer */
#endif
alarm, /* audible alarm on errors? */
monitor, /* monitor function headers? */
pause, /* pause for operator on errors? */
#ifdef DYNAMIC
*symtab, /* symbol table */
*litq, /* literal pool */
*macn, /* macro name buffer */
*macq, /* macro string buffer */
*pline, /* parsing buffer */
*mline, /* macro buffer */
#else
symtab[SYMTBSZ],
litq[LITABSZ],
macn[MACNSIZE],
macq[MACQSIZE],
pline[LINESIZE],
mline[LINESIZE],
swq[SWTABSZ],
#endif
*line, /* points to pline or mline */
*lptr, /* ptr to either */
*glbptr, /* ptrs to next entries */
*locptr, /* ptr to next local symbol */
quote[2], /* literal string for '"' */
*cptr, /* work ptrs to any char buffer */
*cptr2,
*cptr3,
msname[NAMESIZE], /* macro symbol name array */
ssname[NAMESIZE]; /* static symbol name array */
#include "cc11.c"
#include "cc12.c"
#include "cc13.c"
#ifndef SEPARATE
#include "cc21.c"
#include "cc22.c"
#include "cc31.c"
#include "cc32.c"
#include "cc33.c"
#include "cc41.c"
#include "cc42.c"
#endif
>>> CC11.C 5513
/*
** execution begins here
*/
main(argc, argv) int argc, *argv; {
fputs(VERSION, stderr);
fputs(CRIGHT1, stderr);
argcs=argc;
argvs=argv;
#ifdef DYNAMIC
swnext=calloc(SWTABSZ, 1);
swend=swnext+((SWTABSZ-SWSIZ)>>1);
stage=calloc(STAGESIZE, 2*BPW);
wq=calloc(WQTABSZ, BPW);
litq=calloc(LITABSZ, 1);
macn=calloc(MACNSIZE, 1);
macq=calloc(MACQSIZE, 1);
pline=calloc(LINESIZE, 1);
mline=calloc(LINESIZE, 1);
#else
swend=(swnext=swq)+SWTABSZ-SWSIZ;
#endif
stagelast=stage+(STAGESIZE*2*BPW);
swactive= /* not in switch */
stagenext= /* direct-output mode */
iflevel= /* #if... nesting level = 0 */
skiplevel= /* #if... not encountered */
macptr= /* clear the macro pool */
csp = /* stack ptr (relative) */
errflag= /* not skipping errors till ";" */
eof= /* not eof yet */
ncmp= /* not in compound statement */
files=
filearg=
quote[1]=0;
func1= /* first function */
ccode=1; /* enable preprocessing */
wqptr=wq; /* clear while queue */
quote[0]='"'; /* fake a quote literal */
input=input2=EOF;
ask(); /* get user options */
openfile(); /* and initial input file */
preprocess(); /* fetch first line */
#ifdef DYNAMIC
symtab=calloc((NUMLOCS*SYMAVG + NUMGLBS*SYMMAX), 1);
#endif
locptr=STARTLOC;
glbptr=STARTGLB;
glbflag=1;
ctext=0;
header(); /* intro code */
setops(); /* set values in op arrays */
parse(); /* process ALL input */
outside(); /* verify outside any function */
trailer(); /* follow-up code */
fclose(output);
}
/*
** process all input text
**
** At this level, only static declarations,
** defines, includes and function
** definitions are legal...
*/
parse() {
while (eof==0) {
if(amatch("extern", 6)) dodeclare(EXTERNAL);
else if(amatch("static", 6)) dodeclare(STATIC);
else if(dodeclare(GLOBAL)) ;
else if(match("#asm")) doasm();
else if(match("#include")) doinclude();
else if(match("#define")) addmac();
else newfunc();
blanks(); /* force eof if pending */
}
}
/*
** dump the literal pool
*/
dumplits(size) int size; {
int j, k; k=0;
while (k < litptr) {
poll(1); /* allow program interruption */
if (size == 1) gen_code(_DB, NULL);
else gen_code(_DW, NULL);
j = 10;
while(j--) {
outdec(getint(litq+k, size));
k += size;
if(j == 0 || k >= litptr) {nl(); break;}
outbyte(',');
}
}
}
/*
** dump zeroes for default initial values
*/
dumpzero(size, count) int size, count; {
if(count > 0) {
if (size == 1) gen_code(_DBZERO, count);
else gen_code(_DWZERO, count);
}
}
/*
** verify compile ends outside any function
*/
outside() {
if (ncmp) error("no closing bracket");
}
/*
** get run options
*/
ask() {
int i;
i=listfp=nxtlab=0;
output=stdout;
#ifdef OPTIMIZE
optimize=YES;
#endif
alarm=monitor=pause=NO;
line=mline;
while(getarg(++i, line, LINESIZE, argcs, argvs)!=EOF) {
if(line[0]!='-') continue;
if((toupper(line[1])=='L')&(isdigit(line[2]))&(line[3]<=' ')) {
listfp=line[2]-'0';
continue;
}
#ifdef OPTIMIZE
if(toupper(line[1])=='N' && toupper(line[2])=='O' && line[3]<=' ') {
optimize=NO;
continue;
}
#endif
if(line[2]<=' ') {
if(toupper(line[1])=='A') {alarm=YES; continue;}
if(toupper(line[1])=='M') {monitor=YES; continue;}
if(toupper(line[1])=='P') {pause=YES; continue;}
}
#ifndef LINK
if(toupper(line[1])=='B') {
bump(0); bump(2);
if(number(&nxtlab)) continue;
}
#endif
sout("usage: cc [file]... [-m] [-a] [-p] [-l#]", stderr);
#ifdef OPTIMIZE
sout(" [-no]", stderr);
#endif
#ifndef LINK
sout(" [-b#]", stderr);
#endif
sout("\n", stderr);
abort(ERRCODE);
}
}
/*
** input and output file opens
*/
openfile() { /* entire function revised */
char outfn[15];
int i, j, ext;
input=EOF;
while(getarg(++filearg, pline, LINESIZE, argcs, argvs)!=EOF) {
if(pline[0]=='-') continue;
ext = NO;
i = -1;
j = 0;
while(pline[++i]) {
if(pline[i] == '.') {
ext = YES;
break;
}
if(j < 10) outfn[j++] = pline[i];
}
if(!ext) {
strcpy(pline + i, ".C");
}
input = mustopen(pline, "r");
if(!files && isatty(stdout)) {
strcpy(outfn + j, ".ASM");
output = mustopen(outfn, "w");
}
files=YES;
kill();
return;
}
if(files++) eof=YES;
else input=stdin;
kill();
}
/*
** open a file with error checking
*/
mustopen(fn, mode) char *fn, *mode; {
int fd;
if(fd = fopen(fn, mode)) return fd;
sout("open error on ", stderr);
lout(fn, stderr);
abort(ERRCODE);
}
setops() {
op2[ 0]= op[ 0]= _OR; /* heir5 */
op2[ 1]= op[ 1]= _XOR; /* heir6 */
op2[ 2]= op[ 2]= _AND; /* heir7 */
op2[ 3]= op[ 3]= _EQ; /* heir8 */
op2[ 4]= op[ 4]= _NE;
op2[ 5]=_ULE; op[ 5]= _LE; /* heir9 */
op2[ 6]=_UGE; op[ 6]= _GE;
op2[ 7]=_ULT; op[ 7]= _LT;
op2[ 8]=_UGT; op[ 8]= _GT;
op2[ 9]= op[ 9]= _ASR; /* heir10 */
op2[10]= op[10]= _ASL;
op2[11]= op[11]= _ADD; /* heir11 */
op2[12]= op[12]= _SUB;
op2[13]= op[13]=_MULT; /* heir12 */
op2[14]= op[14]= _DIV;
op2[15]= op[15]= _MOD;
}
>>> CC12.C 7088
/*
** open an include file
*/
doinclude() {
int i; char str[30];
blanks(); /* skip over to name */
if(*lptr == '"' || *lptr == '<') ++lptr;
i=0;
while(lptr[i] && lptr[i] != '"' && lptr[i] != '>' && lptr[i] != '\n') {
str[i] = lptr[i];
++i;
}
str[i] = NULL;
if((input2=fopen(str,"r")) == NULL) {
input2 = EOF;
error("open failure on include file");
}
kill(); /* make next read come from new file (if open) */
}
/*
** test for global declarations
*/
dodeclare(class) int class; {
if(amatch("char",4)) {
declglb(CCHAR, class);
ns();
return 1;
}
else if((amatch("int",3))|(class==EXTERNAL)|(class==STATIC)) {
declglb(CINT, class);
ns();
return 1;
}
return 0;
}
/*
** declare a static variable
*/
declglb(type, class) int type, class; {
int k, j;
while(1) {
if(endst()) return; /* do line */
if(match("(*")|match("*")) {
j=POINTER;
k=0;
}
else {
j=VARIABLE;
k=1;
}
if (symname(ssname, YES)==0) illname();
if(findglb(ssname)) multidef(ssname);
if(match(")")) ;
if(match("()")) j=FUNCTION;
else if (match("[")) {
paerror(j);
k=needsub(); /* get size */
j=ARRAY; /* !0=array */
}
if(class==EXTERNAL) external(ssname, type>>2, j);
else if(j!=FUNCTION) j=initials(type>>2, j, k);
addsym(ssname, j, type, k, &glbptr, class);
if (match(",")==0) return; /* more? */
}
}
/*
** declare local variables
*/
declloc(typ) int typ; {
int k,j;
if(swactive) error("not allowed in switch");
#ifdef STGOTO
if(noloc) error("not allowed with goto");
#endif
if(declared < 0) error("must declare first in block");
while(1) {
while(1) {
if(endst()) return;
if(match("(*") | match("*")) j=POINTER;
else j=VARIABLE;
if (symname(ssname, YES)==0) illname();
if(match(")")) ;
if(match("()")) j=FUNCTION;
/* no multidef check, block-locals are together */
k=BPW;
if (match("[")) {
paerror(j);
if(k=needsub()) {
j=ARRAY;
if(typ==CINT)k=k<<LBPW;
}
else {j=POINTER; k=BPW;}
}
else if((typ==CCHAR)&(j==VARIABLE)) k=SBPC;
declared = declared + k;
addsym(ssname, j, typ, csp - declared, &locptr, AUTOMATIC);
break;
}
if (match(",")==0) return;
}
}
/*
** test for pointer array (unsupported)
*/
paerror(j) int j; {
if(j==POINTER) error("no pointer arrays");
}
/*
** initialize global objects
*/
initials(size, ident, dim) int size, ident, dim; {
int savedim;
litptr=0;
if(dim==0) dim = -1;
savedim=dim;
public(size, ident);
if(match("=")) {
if(match("{")) {
while(dim) {
init(size, ident, &dim);
if(match(",")==0) break;
}
needtoken("}");
}
else init(size, ident, &dim);
}
if((dim == -1)&(dim==savedim)) {
stowlit(0, size=BPW);
ident=POINTER;
}
dumplits(size);
dumpzero(size, dim);
return ident;
}
/*
** evaluate one initializer
*/
init(size, ident, dim) int size, ident, *dim; {
int value;
if(qstr(&value)) {
if((ident==VARIABLE)|(size!=1))
error("must assign to char pointer or array");
*dim = *dim - (litptr - value);
if(ident==POINTER) point();
}
else if(constexpr(&value)) {
if(ident==POINTER) error("cannot assign to pointer");
stowlit(value, size);
*dim = *dim - 1;
}
}
/*
** get required array size
*/
needsub() {
int val;
if(match("]")) return 0; /* null size */
if (constexpr(&val)==0) val=1;
if (val<0) {
error("negative size illegal");
val = -val;
}
needtoken("]"); /* force single dimension */
return val; /* and return size */
}
/*
** begin a function
**
** called from "parse" and tries to make a function
** out of the following text
*/
newfunc() {
char *ptr;
#ifdef STGOTO
nogo = /* enable goto statements */
noloc = 0; /* enable block-local declarations */
#endif
lastst= /* no statement yet */
litptr=0; /* clear lit pool */
litlab=getlabel(); /* label next lit pool */
locptr=STARTLOC; /* clear local variables */
if(monitor) lout(line, stderr);
if (symname(ssname, YES)==0) {
error("illegal function or declaration");
kill(); /* invalidate line */
return;
}
if(ptr=findglb(ssname)) { /* already in symbol table ? */
if(ptr[IDENT]!=FUNCTION) multidef(ssname);
else if(ptr[OFFSET]==FUNCTION) multidef(ssname);
else {
/* earlier assumed to be a function */
ptr[OFFSET]=FUNCTION;
ptr[CLASS]=GLOBAL;
}
}
else
addsym(ssname, FUNCTION, CINT, FUNCTION, &glbptr, GLOBAL);
if(match("(")==0) error("no open paren");
public(CINT>>2, FUNCTION);
locptr=STARTLOC;
argstk=0; /* init arg count */
while(match(")")==0) { /* then count args */
/* any legal name bumps arg count */
if(symname(ssname, YES)) {
if(findloc(ssname)) multidef(ssname);
else {
addsym(ssname, 0, 0, argstk, &locptr, AUTOMATIC);
argstk=argstk+BPW;
}
}
else {error("illegal argument name");junk();}
blanks();
/* if not closing paren, should be comma */
if(streq(lptr,")")==0) {
if(match(",")==0) error("no comma");
}
if(endst()) break;
}
csp=0; /* preset stack ptr */
argtop=argstk+BPW; /* account for the pushed BP */
while(argstk) {
/* now let user declare what types of things */
/* those arguments were */
if(amatch("char",4)) {doargs(CCHAR);ns();}
else if(amatch("int",3)) {doargs(CINT);ns();}
else {error("wrong number of arguments");break;}
}
gen_code(_FUNC, 0);
statement();
#ifdef STGOTO
if(lastst != STRETURN && lastst != STGOTO) gen_code(_RET, 0);
#else
if(lastst != STRETURN) gen_code(_RET, 0);
#endif
if(litptr) {
toseg(DATASEG);
gen_code(_RLAB, litlab);
dumplits(1); /* dump literals */
}
}
/*
** declare argument types
**
** called from "newfunc" this routine adds an entry in the
** local symbol table for each named argument. The arguments are
** of type 't'.
*/
doargs(t) int t; {
int j, legalname;
char c, *argptr;
while(1) {
if(argstk==0) return; /* no arguments */
if(match("(*")|match("*")) j=POINTER; else j=VARIABLE;
if((legalname=symname(ssname, YES))==0) illname();
if(match(")")) ;
if(match("()")) ;
if(match("[")) { /* is it a pointer? */
paerror(j);
while(inbyte()!=']') if(endst()) break; /*skip "[...]" */
j=POINTER; /* add entry as pointer */
}
if(legalname) {
if(argptr=findloc(ssname)) {
/* add details of type and address */
argptr[IDENT]=j;
argptr[TYPE]=t;
putint(argtop-getint(argptr+OFFSET, OFFSIZE), argptr+OFFSET, OFFSIZE);
}
else error("not an argument");
}
argstk=argstk-BPW; /* cnt down */
if(endst())return;
if(match(",")==0) error("no comma");
}
}
>>> CC13.C 7407
/*
** statement parser
**
** called whenever syntax requires a statement
** this routine performs that statement
** and returns a number telling which one
*/
statement() {
if ((ch==0) & (eof)) return;
else if(amatch("static",6)){declglb(STATIC);ns();}
else if(amatch("char",4)) {declloc(CCHAR);ns();}
else if(amatch("int",3)) {declloc(CINT);ns();}
else {
if(declared >= 0) {
#ifdef STGOTO
if(ncmp > 1) nogo=declared; /* disable goto if any */
#endif
gen_code(_MODSTK, csp - declared);
declared = -1;
}
if(match("{")) compound();
else if(amatch("if",2)) {doif(); lastst=STIF;}
else if(amatch("while",5)) {dowhile(); lastst=STWHILE;}
#ifdef STDO
else if(amatch("do",2)) {dodo(); lastst=STDO;}
#endif
#ifdef STFOR
else if(amatch("for",3)) {dofor(); lastst=STFOR;}
#endif
#ifdef STSWITCH
else if(amatch("switch",6)) {doswitch(); lastst=STSWITCH;}
else if(amatch("case",4)) {docase(); lastst=STCASE;}
else if(amatch("default",7)) {dodefault(); lastst=STDEF;}
#endif
#ifdef STGOTO
else if(amatch("goto", 4)) {dogoto(); lastst=STGOTO;}
else if(dolabel()) lastst=STLABEL;
#endif
else if(amatch("return",6)) {doreturn();ns(); lastst=STRETURN;}
else if(amatch("break",5)) {dobreak();ns(); lastst=STBREAK;}
else if(amatch("continue",8)){docont();ns(); lastst=STCONT;}
else if(match(";")) errflag=0;
else if(match("#asm")) {doasm(); lastst=STASM;}
else {doexpr();ns(); lastst=STEXPR;}
}
return lastst;
}
/*
** semicolon enforcer
**
** called whenever syntax requires a semicolon
*/
ns() {
if(match(";")==0) error("no semicolon");
else errflag=0;
}
compound() {
int savcsp;
char *savloc;
savcsp=csp;
savloc=locptr;
declared=0; /* may now declare local variables */
++ncmp; /* new level open */
while (match("}")==0)
if(eof) {
error("no final }");
break;
}
else statement(); /* do one */
--ncmp; /* close current level */
#ifdef STGOTO
if(lastst != STRETURN && lastst != STGOTO)
#else
if(lastst != STRETURN)
#endif
gen_code(_MODSTK, savcsp); /* delete local variable space */
csp = savcsp;
#ifdef STGOTO
cptr=savloc; /* retain labels */
while(cptr < locptr) {
cptr2=nextsym(cptr);
if(cptr[IDENT] == LABEL) {
while(cptr < cptr2) *savloc++ = *cptr++;
}
else cptr=cptr2;
}
#endif
locptr=savloc; /* delete local symbols */
declared = -1; /* may not declare variables */
}
doif() {
int flab1,flab2;
flab1=getlabel(); /* get label for false branch */
test(flab1, YES); /* get expression, and branch false */
statement(); /* if true, do a statement */
if (amatch("else",4)==0) { /* if...else ? */
/* simple "if"...print false label */
gen_code(_LABEL, flab1);
return; /* and exit */
}
flab2=getlabel();
#ifdef STGOTO
if((lastst != STRETURN)&(lastst != STGOTO)) gen_code(_JUMP, flab2);
#else
if(lastst != STRETURN) gen_code(_JUMP, flab2);
#endif
gen_code(_LABEL, flab1); /* print false label */
statement(); /* and do "else" clause */
gen_code(_LABEL, flab2); /* print true label */
}
doexpr() {
int const, val;
int *before, *start;
while(1) {
setstage(&before, &start);
expression(&const, &val);
clearstage(before, start);
if(ch != ',') break;
bump(1);
}
}
dowhile() {
int wq[4]; /* allocate local queue */
addwhile(wq); /* add entry to queue for "break" */
gen_code(_LABEL, wq[WQLOOP]); /* loop label */
test(wq[WQEXIT], YES); /* see if true */
statement(); /* if so, do a statement */
gen_code(_JUMP, wq[WQLOOP]); /* loop to label */
gen_code(_LABEL, wq[WQEXIT]); /* exit label */
delwhile(); /* delete queue entry */
}
#ifdef STDO
dodo() {
int wq[4], top;
addwhile(wq);
gen_code(_LABEL, top=getlabel());
statement();
needtoken("while");
gen_code(_LABEL, wq[WQLOOP]);
test(wq[WQEXIT], YES);
gen_code(_JUMP, top);
gen_code(_LABEL, wq[WQEXIT]);
delwhile();
ns();
}
#endif
#ifdef STFOR
dofor() {
int wq[4], lab1, lab2;
addwhile(wq);
lab1=getlabel();
lab2=getlabel();
needtoken("(");
if(match(";")==0) {
doexpr(); /* expr 1 */
ns();
}
gen_code(_LABEL, lab1);
if(match(";")==0) {
test(wq[WQEXIT], NO); /* expr 2 */
ns();
}
gen_code(_JUMP, lab2);
gen_code(_LABEL, wq[WQLOOP]);
if(match(")")==0) {
doexpr(); /* expr 3 */
needtoken(")");
}
gen_code(_JUMP, lab1);
gen_code(_LABEL, lab2);
statement();
gen_code(_JUMP, wq[WQLOOP]);
gen_code(_LABEL, wq[WQEXIT]);
delwhile();
}
#endif
#ifdef STSWITCH
doswitch() {
int wq[4], endlab, swact, swdef, *swnex, *swptr;
swact=swactive;
swdef=swdefault;
swnex=swptr=swnext;
addwhile(wq);
*(wqptr + WQLOOP - WQSIZ) = 0;
needtoken("(");
doexpr(); /* evaluate switch expression */
needtoken(")");
swdefault=0;
swactive=1;
gen_code(_JUMP, endlab=getlabel());
statement(); /* cases, etc. */
gen_code(_JUMP, wq[WQEXIT]);
gen_code(_LABEL, endlab);
gen_code(_SW, 0); /* match cases */
while(swptr < swnext) {
gen_code(_DEFLABEL, *swptr++);
gen_code(_DEFWORD, *swptr++); /* case value */
}
gen_code(_DEFWORD, 0);
if(swdefault) gen_code(_JUMP, swdefault);
gen_code(_LABEL, wq[WQEXIT]);
delwhile();
swnext=swnex;
swdefault=swdef;
swactive=swact;
}
docase() {
if(swactive==0) error("not in switch");
if(swnext > swend) {
error("too many cases");
return;
}
gen_code(_LABEL, *swnext++ = getlabel());
constexpr(swnext++);
needtoken(":");
}
dodefault() {
if(swactive) {
if(swdefault) error("multiple defaults");
}
else error("not in switch");
needtoken(":");
gen_code(_LABEL, swdefault=getlabel());
}
#endif
#ifdef STGOTO
dogoto() {
if(nogo > 0) error("not allowed with block-locals");
else noloc = 1;
if(symname(ssname, YES)) gen_code(_JUMP, addlabel());
else error("bad label");
ns();
}
dolabel() {
char *savelptr;
blanks();
savelptr=lptr;
if(symname(ssname, YES)) {
if(gch()==':') {
gen_code(_LABEL, addlabel());
return 1;
}
else bump(savelptr-lptr);
}
return 0;
}
addlabel() {
if(cptr=findloc(ssname)) {
if(cptr[IDENT]!=LABEL) error("not a label");
}
else cptr=addsym(ssname, LABEL, LABEL, getlabel(), &locptr, LABEL);
return (getint(cptr+OFFSET, OFFSIZE));
}
#endif
doreturn() {
int savcsp;
if(endst()==0) doexpr();
savcsp = csp;
gen_code(_MODSTK, 0);
gen_code(_RET, 0);
csp = savcsp;
}
dobreak() {
int *ptr;
if ((ptr=readwhile(wqptr))==0) return;
gen_code(_MODSTK, ptr[WQSP]);
gen_code(_JUMP, ptr[WQEXIT]);
}
docont() {
int *ptr;
ptr = wqptr;
while (1) {
if ((ptr=readwhile(ptr))==0) return;
if (ptr[WQLOOP]) break;
}
gen_code(_MODSTK, ptr[WQSP]);
gen_code(_JUMP, ptr[WQLOOP]);
}
doasm() {
ccode=0; /* mark mode as "asm" */
while (1) {
inline();
if (match("#endasm")) break;
if(eof)break;
sout(line, output);
}
kill();
ccode=1;
}
>>> CC2.C 650
/*
** Small-C Compiler Part 2
*/
#include <stdio.h>
#include "cc.def"
extern char
#ifdef DYNAMIC
*symtab,
*macn,
*macq,
*pline,
*mline,
#else
symtab[SYMTBSZ],
macn[MACNSIZE],
macq[MACQSIZE],
pline[LINESIZE],
mline[LINESIZE],
#endif
#ifdef OPTIMIZE
optimize,
#endif
alarm, *glbptr, *line, *lptr, *cptr, *cptr2, *cptr3,
*locptr, msname[NAMESIZE], pause, quote[2];
extern int
#ifdef DYNAMIC
*wq,
#else
wq[WQTABSZ],
#endif
ccode, ch, csp, eof, errflag, iflevel,
input, input2, listfp, macptr, nch,
nxtlab, op[16], opindex, opsize, output, pptr,
skiplevel, *wqptr;
#include "cc21.c"
#include "cc22.c"
>>> CC21.C 4262
junk() {
if(an(inbyte())) while(an(ch)) gch();
else while(an(ch)==0) {
if(ch==0) break;
gch();
}
blanks();
}
endst() {
blanks();
return ((streq(lptr,";")|(ch==0)));
}
illname() {
error("illegal symbol");
junk();
}
multidef(sname) char *sname; {
error("already defined");
}
undef(sname) char *sname; {
error("undefined");
}
needtoken(str) char *str; {
if (match(str)==0) error("missing token");
}
needlval() {
error("must be lvalue");
}
findglb(sname) char *sname; {
if(search(sname, STARTGLB, SYMMAX, ENDGLB, NUMGLBS, NAME)) return cptr;
return 0;
}
findloc(sname) char *sname; {
cptr = locptr - 1; /* search backward for block locals */
while(cptr > STARTLOC) {
cptr = cptr - *cptr;
if(astreq(sname, cptr, NAMEMAX)) return (cptr - NAME);
cptr = cptr - NAME - 1;
}
return 0;
}
addsym(sname, id, typ, value, lgptrptr, class)
char *sname, id, typ; int value, *lgptrptr, class; {
if(lgptrptr == &glbptr) {
if(cptr2=findglb(sname)) return cptr2;
if(cptr==0) {
error("global symbol table overflow");
return 0;
}
}
else {
if(locptr > (ENDLOC-SYMMAX)) {
error("local symbol table overflow");
abort(ERRCODE);
}
cptr = *lgptrptr;
}
cptr[IDENT]=id;
cptr[TYPE]=typ;
cptr[CLASS]=class;
putint(value, cptr+OFFSET, OFFSIZE);
cptr3 = cptr2 = cptr + NAME;
while(an(*sname)) *cptr2++ = *sname++;
if(lgptrptr == &locptr) {
*cptr2 = cptr2 - cptr3; /* set length */
*lgptrptr = ++cptr2;
}
return cptr;
}
nextsym(entry) char *entry; {
entry = entry + NAME;
while(*entry++ >= ' '); /* find length byte */
return entry;
}
/*
** get integer of length len from address addr
** (byte sequence set by "putint")
*/
getint(addr, len) char *addr; int len; {
int i;
i = *(addr + --len); /* high order byte sign extended */
while(len--) i = (i << 8) | *(addr+len)&255;
return i;
}
/*
** put integer i of length len into address addr
** (low byte first)
*/
putint(i, addr, len) char *addr; int i, len; {
while(len--) {
*addr++ = i;
i = i>>8;
}
}
/*
** test if next input string is legal symbol name
*/
symname(sname, ucase) char *sname; int ucase; {
int k;char c;
blanks();
if(alpha(ch)==0) return (*sname=0); /*19*/
k=0;
while(an(ch)) {
#ifdef UPPER
if(ucase)
sname[k]=toupper(gch());
else
#endif
sname[k]=gch();
if(k<NAMEMAX) ++k;
}
sname[k]=0;
return 1;
}
/*
** return next avail internal label number
*/
getlabel() {
return(++nxtlab);
}
/*
** test if c is alphabetic
*/
alpha(c) char c; {
return (isalpha(c) | c=='_');
}
/*
** test if given character is alphanumeric
*/
an(c) char c; {
return (alpha(c) | isdigit(c));
}
addwhile(ptr) int ptr[]; {
int k;
ptr[WQSP]=csp; /* and stk ptr */
ptr[WQLOOP]=getlabel(); /* and looping label */
ptr[WQEXIT]=getlabel(); /* and exit label */
if (wqptr==WQMAX) {
error("too many active loops");
abort(ERRCODE);
}
k=0;
while (k<WQSIZ) *wqptr++ = ptr[k++];
}
delwhile() {
if (wqptr > wq) wqptr=wqptr-WQSIZ;
}
readwhile(ptr) int *ptr; {
if (ptr <= wq) {
error("out of context");
return 0;
}
else return (ptr-WQSIZ);
}
white() {
#ifdef DYNAMIC
/* test for stack/prog overlap at deepest nesting */
/* primary -> symname -> blanks -> white */
avail(YES); /* abort on stack/symbol table overflow */
#endif
return ((*lptr<= ' ') & (*lptr!=NULL));
}
gch() {
int c;
if(c=ch) bump(1);
return c;
}
bump(n) int n; {
if(n) lptr=lptr+n;
else lptr=line;
if(ch = nch = *lptr) nch = *(lptr+1);
}
kill() {
*line=0;
bump(0);
}
inbyte() {
while(ch==0) {
if (eof) return 0;
preprocess();
}
return gch();
}
inline() { /* numerous revisions */
int k,unit;
poll(1); /* allow operator interruption */
if (input==EOF) openfile();
if(eof) return;
if((unit=input2)==EOF) unit=input;
if(fgets(line, LINEMAX, unit)==NULL) {
fclose(unit);
if(input2!=EOF) input2=EOF;
else input=EOF;
*line=NULL;
}
else if(listfp) {
if(listfp==output) cout(';', output);
sout(line, listfp);
}
bump(0);
}
>>> CC22.C 6770
ifline() {
while(1) {
inline();
if(eof) return;
if(match("#ifdef")) {
++iflevel;
if(skiplevel) continue;
symname(msname, NO);
if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0)
skiplevel=iflevel;
continue;
}
if(match("#ifndef")) {
++iflevel;
if(skiplevel) continue;
symname(msname, NO);
if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0))
skiplevel=iflevel;
continue;
}
if(match("#else")) {
if(iflevel) {
if(skiplevel==iflevel) skiplevel=0;
else if(skiplevel==0) skiplevel=iflevel;
}
else noiferr();
continue;
}
if(match("#endif")) {
if(iflevel) {
if(skiplevel==iflevel) skiplevel=0;
--iflevel;
}
else noiferr();
continue;
}
if(skiplevel) continue;
#ifdef OLDCC
if((listfp!=0) & (*line!=NULL)) {
if(listfp==output) cout(';', output);
sout(line, listfp); /*19*/
}
if(ch==NEWLINE) continue;
#else
if(ch==0) continue;
break;
}
}
keepch(c) char c; {
if(pptr<LINEMAX) pline[++pptr]=c;
}
preprocess() {
int k;
char c;
if(ccode) {
line=mline;
ifline();
if(eof) return;
}
else {
line=pline;
inline();
return;
}
pptr = -1;
while(ch != NEWLINE && ch) {
if(white()) {
keepch(' ');
while(white()) gch();
}
else if(ch=='"') {
keepch(ch);
gch();
while((ch!='"')|((*(lptr-1)==92)&(*(lptr-2)!=92))) {
if(ch==NULL) {
error("no quote");
break;
}
keepch(gch());
}
gch();
keepch('"');
}
else if(ch==39) {
keepch(39);
gch();
while((ch!=39)|((*(lptr-1)==92)&(*(lptr-2)!=92))) {
if(ch==NULL) {
error("no apostrophe");
break;
}
keepch(gch());
}
gch();
keepch(39);
}
else if((ch=='/')&(nch=='*')) {
bump(2);
while(((ch=='*')&(nch=='/'))==0) {
if(ch) bump(1);
else {
ifline();
if(eof) break;
}
}
bump(2);
}
else if(an(ch)) {
k=0;
while((an(ch)) & (k<NAMEMAX)) {
msname[k++]=ch;
gch();
}
msname[k]=NULL;
if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)) {
k=getint(cptr+NAMESIZE, 2);
while(c=macq[k++]) keepch(c);
while(an(ch)) gch();
}
else {
k=0;
while(c=msname[k++]) keepch(c);
}
}
else keepch(gch());
}
if(pptr>=LINEMAX) error("line too long");
keepch(NULL);
line=pline;
bump(0);
}
noiferr() {
error("no matching #if...");
errflag=0;
}
addmac() {
int k;
if(symname(msname, NO)==0) {
illname();
kill();
return;
}
k=0;
if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0) {
if(cptr2=cptr) while(*cptr2++ = msname[k++]);
else {
error("macro name table full");
return;
}
}
putint(macptr, cptr+NAMESIZE, 2);
while(white()) gch();
while(putmac(gch()));
if(macptr>=MACMAX) {
error("macro string queue full"); abort(ERRCODE);
}
}
putmac(c) char c; {
macq[macptr]=c;
if(macptr<MACMAX) ++macptr;
return c;
}
/*
** search for symbol match
** on return cptr points to slot found or empty slot
*/
search(sname, buf, len, end, max, off)
char *sname, *buf, *end; int len, max, off; {
cptr=cptr2=buf+((hash(sname)%(max-1))*len);
while(*cptr != NULL) {
if(astreq(sname, cptr+off, NAMEMAX)) return 1;
if((cptr=cptr+len) >= end) cptr=buf;
if(cptr == cptr2) return (cptr=0);
}
return 0;
}
hash(sname) char *sname; {
int i, c;
i=0;
while(c = *sname++) i=(i<<1)+c;
return i;
}
outdec(number) int number; {
int k,zs;
char c, *q, *r;
zs = 0;
k=10000;
if (number<0) {
number=(-number);
outbyte('-');
}
while (k>=1) {
q=0; r=number;
while(r >= k) {++q; r = r - k;}
c = q + '0';
if ((c!='0')|(k==1)|(zs)) {
zs=1;
outbyte(c);
}
number=r;
k=k/10;
}
}
ol(ptr) char ptr[]; {
ot(ptr);
nl();
}
ot(ptr) char ptr[]; {
outstr(ptr);
}
outstr(ptr) char ptr[]; {
poll(1); /* allow program interruption */
/* must work with symbol table names terminated by length */
while(*ptr >= ' ') outbyte(*ptr++);
}
/*
** output a name so that it can't look like a reserved word
*/
outname(ptr) char ptr[]; {
outstr("_");
while(*ptr >= ' ') outbyte(toupper(*ptr++));
}
outbyte(c) char c; {
cout(c,output);
return c;
}
cout(c, fd) char c; int fd; {
if(fputc(c, fd)==EOF) xout();
}
sout(string, fd) char *string; int fd; {
if(fputs(string, fd)==EOF) xout();
}
lout(line, fd) char *line; int fd; {
sout(line, fd);
cout(NEWLINE, fd);
}
xout() {
fputs("output error", stderr);
abort(ERRCODE);
}
nl() {
outbyte(NEWLINE);
}
col() {
#ifdef COL
outbyte(':');
#endif
}
error(msg) char msg[]; {
if(errflag) return; else errflag=1;
lout(line, stderr);
errout(msg, stderr);
if(alarm) fputc(7, stderr);
if(pause) while(fgetc(stderr) != NEWLINE);
if(listfp>0) errout(msg, listfp);
}
errout(msg, fp) char msg[]; int fp; {
int k; k=line+2;
while(k++ <= lptr) cout(' ', fp);
lout("/\\", fp);
sout("**** ", fp); lout(msg, fp);
}
streq(str1,str2) char str1[],str2[]; {
int k;
k=0;
while (str2[k]) {
if ((str1[k])!=(str2[k])) return 0;
++k;
}
return k;
}
astreq(str1,str2,len) char str1[],str2[];int len; {
int k;
k=0;
while (k<len) {
if ((str1[k])!=(str2[k]))break;
/*
** must detect end of symbol table names terminated by
** symbol length in binary
*/
if(str1[k] < ' ') break;
if(str2[k] < ' ') break;
++k;
}
if (an(str1[k]))return 0;
if (an(str2[k]))return 0;
return k;
}
match(lit) char *lit; {
int k;
blanks();
if (k=streq(lptr,lit)) {
bump(k);
return 1;
}
return 0;
}
amatch(lit,len) char *lit;int len; {
int k;
blanks();
if (k=astreq(lptr,lit,len)) {
bump(k);
while(an(ch)) inbyte();
return 1;
}
return 0;
}
nextop(list) char *list; {
char op[4];
opindex=0;
blanks();
while(1) {
opsize=0;
while(*list > ' ') op[opsize++] = *list++;
op[opsize]=0;
if(opsize=streq(lptr, op))
if((*(lptr+opsize) != '=')&
(*(lptr+opsize) != *(lptr+opsize-1)))
return 1;
if(*list) {
++list;
++opindex;
}
else return 0;
}
}
blanks() {
while(1) {
while(ch) {
if(white()) gch();
else return;
}
if(line==mline) return;
preprocess();
if(eof)break;
}
}
>>> CC3.C 902
/*
** Small-C Compiler Part 3
*/
#include <stdio.h>
#include "cc.def"
extern char
#ifdef DYNAMIC
*litq,
#else
litq[LITABSZ],
#endif
*glbptr, *lptr, ssname[NAMESIZE], quote[2];
extern int
ch, csp, litlab, litptr, nch, op[16], op2[16],
oper, opindex, opsize, *stagenext;
/* entries in lval[] */
#define SYMTBL 0 /* symbol table address, else 0 for constant */
#define TYPEIND 1 /* type of indirect obj to fetch, else 0 for static */
#define TYPEPA 2 /* type of pointer or array, else 0 for all other */
#define CONEXP 3 /* true if constant expression */
#define CONVAL 4 /* value of constant expression */
#define REG2 5 /* true if secondary register altered*/
#define OPER 6 /* code of highest/last binary operator */
#define STAGE 7 /* stage address of "oper 0" code, else 0 */
#include "cc31.c"
#include "cc32.c"
#include "cc33.c"
>>> CC31.C 8321
/*
** lval[0] - symbol table address, else 0 for constant
** lval[1] - type of indirect obj to fetch, else 0 for static
** lval[2] - type of pointer or array, else 0 for all other
** lval[3] - true if constant expression
** lval[4] - value of constant expression (+ auxiliary uses)
** lval[5] - true if secondary register altered
** lval[6] - code of highest/last binary operator
** lval[7] - stage address of "oper 0" code, else 0
*/
/*
** skim over terms adjoining || and && operators
*/
skim(opstr, testfunc, dropval, endval, hier, lval)
char *opstr;
int testfunc, dropval, endval, (*hier)(), lval[]; {
int k, hits, droplab, endlab;
hits=0;
while(1) {
k=plnge1(hier, lval);
if(nextop(opstr)) {
bump(opsize);
if(hits==0) {
hits=1;
droplab=getlabel();
}
dropout(k, testfunc, droplab, lval);
}
else if(hits) {
dropout(k, testfunc, droplab, lval);
gen_code(_IMMED, endval);
gen_code(_JUMP, endlab=getlabel());
gen_code(_LABEL, droplab);
gen_code(_IMMED, dropval);
gen_code(_LABEL, endlab);
lval[TYPEIND] = lval[TYPEPA] = lval[CONEXP] =
lval[CONVAL] = lval[STAGE] = 0;
return 0;
}
else return k;
}
}
/*
** test for early dropout from || or && evaluations
*/
dropout(k, testfunc, exit1, lval)
int k, testfunc, exit1, lval[]; {
if(k) rvalue(lval);
else if(lval[CONEXP]) gen_code(_IMMED, lval[CONVAL]);
gen_code(testfunc, exit1); /* jumps on false */
}
/*
** plunge to a lower level
*/
plnge(opstr, opoff, hier, lval)
char *opstr;
int opoff, (*hier)(), lval[]; {
int k, lval2[8];
k=plnge1(hier, lval);
if(nextop(opstr)==0) return k;
if(k) rvalue(lval);
while(1) {
if(nextop(opstr)) {
bump(opsize);
opindex=opindex+opoff;
plnge2(op[opindex], op2[opindex], hier, lval, lval2);
}
else return 0;
}
}
/*
** unary plunge to lower level
*/
plnge1(hier, lval) int (*hier)(), lval[]; {
int *before, *start;
int k;
setstage(&before, &start);
k=(*hier)(lval);
if(lval[CONEXP]) clearstage(before,0); /* load constant later */
return k;
}
/*
** binary plunge to lower level
*/
plnge2(oper, oper2, hier, lval, lval2)
int oper, oper2, (*hier)(), lval[], lval2[]; {
int *before, *start;
setstage(&before, &start);
lval[REG2]=1; /* flag secondary register used */
lval[STAGE]=0; /* flag as not "... oper 0" syntax */
if(lval[CONEXP]) { /* constant on left side not yet loaded */
if(plnge1(hier, lval2)) rvalue(lval2);
if(lval[CONVAL]==0) lval[STAGE]=stagenext;
gen_code(_IMMED2, lval[CONVAL]<<dbltest(oper, lval2, lval));
}
else { /* non-constant on left side */
gen_code(_PUSH, 0);
if(plnge1(hier, lval2)) rvalue(lval2);
if(lval2[CONEXP]) { /* constant on right side */
if(lval2[CONVAL]==0) lval[STAGE]=start;
csp+=2;
clearstage(before, 0);
if(oper==_ADD) { /* may test other commutative operators */
gen_code(_IMMED2, lval2[CONVAL]<<dbltest(oper, lval, lval2));
}
else {
gen_code(_MOVE, 0);
gen_code(_IMMED, lval2[CONVAL]<<dbltest(oper, lval, lval2));
}
}
else { /* non-constants on both sides */
gen_code(_POP, 0);
if((oper==_ADD)|(oper==_SUB)) {
if(dbltest(oper, lval, lval2)) gen_code(_DBL, 0);
if(dbltest(oper, lval2, lval)) gen_code(_DBL2, 0);
}
}
}
if(oper) {
if(lval[CONEXP]=lval[CONEXP]&lval2[CONEXP]) {
lval[CONVAL]=calc(lval[CONVAL], oper, lval2[CONVAL]);
clearstage(before, 0);
lval[REG2]=0;
}
else {
if((lval[TYPEPA]==0)&(lval2[TYPEPA]==0)) { /* neither is a pointer */
gen_code(oper, 0);
lval[OPER]=oper; /* identify the operator */
}
else {
gen_code(oper2, 0);
lval[OPER]=oper2; /* identify the operator */
}
}
if(oper==_SUB) {
/* if subtracting two pointers to integers */
if((lval[TYPEPA]==CINT)&(lval2[TYPEPA]==CINT)) {
gen_code(_SWAP, 0);
gen_code(_IMMED, 1);
gen_code(_ASR, 0); /** div by 2 **/
}
}
if((oper==_SUB)|(oper==_ADD)) result(lval, lval2);
}
}
calc(left, oper, right) int left, oper, right; {
switch(oper) {
case _OR: return (left | right);
case _XOR: return (left ^ right);
case _AND: return (left & right);
case _EQ: return (left == right);
case _NE: return (left != right);
case _LE: return (left <= right);
case _GE: return (left >= right);
case _LT: return (left < right);
case _GT: return (left > right);
case _ASR: return (left >> right);
case _ASL: return (left << right);
case _ADD: return (left + right);
case _SUB: return (left - right);
case _MULT: return (left * right);
case _DIV: return (left / right);
case _MOD: return (left % right);
default: return 0;
}
}
expression(const, val) int *const, *val; {
int lval[8];
if(hier1(lval)) rvalue(lval);
if(lval[CONEXP]) {
*const=1;
*val=lval[CONVAL];
}
else *const=0;
}
hier1(lval) int lval[]; {
int k, lval2[8], lval3[2], oper;
k=plnge1(hier2, lval);
if(lval[CONEXP]) gen_code(_IMMED, lval[CONVAL]);
if(match("|=")) oper=_OR;
else if(match("^=")) oper=_XOR;
else if(match("&=")) oper=_AND;
else if(match("+=")) oper=_ADD;
else if(match("-=")) oper=_SUB;
else if(match("*=")) oper=_MULT;
else if(match("/=")) oper=_DIV;
else if(match("%=")) oper=_MOD;
else if(match(">>=")) oper=_ASR;
else if(match("<<=")) oper=_ASL;
else if(match("=")) oper=0;
else return k;
if(k==0) {needlval(); return 0;}
lval3[SYMTBL] = lval[SYMTBL];
lval3[TYPEIND] = lval[TYPEIND];
if(lval[TYPEIND]) { /* if we have a pointer to the variable, save it.*/
if(oper) {
gen_code(_PUSH, 0);
rvalue(lval);
}
plnge2(oper, oper, hier1, lval, lval2);
if(oper) gen_code(_POP, 0);
}
else {
if(oper) {
rvalue(lval);
plnge2(oper, oper, hier1, lval, lval2);
}
else {
if(hier1(lval2)) rvalue(lval2);
lval[REG2]=lval2[REG2];
}
}
store(lval3);
return 0;
}
hier2(lval) int lval[]; {
int k, falselab, endlab;
int *before, *after;
int const, retconst, retval;
retconst = NO; /* assume non-constant */
k = plnge1(hier3, lval);
if (lval[CONEXP] && lval[CONVAL]) const = 1;
else if (lval[CONEXP] && !lval[CONVAL]) const = -1;
else const = 0;
if (match("?")==0) return k;
if (!const) dropout(k, _NE0, falselab = getlabel(), lval);
setstage(&before, &after); /* prepare to delete code */
if (plnge1(hier3, lval)) rvalue(lval);
else if (lval[CONEXP]) gen_code(_IMMED, lval[CONVAL]);
if (const<0) clearstage(before, 0); /* if false, delete 'then' expr */
else if (const>0) {
retconst = lval[CONEXP];
retval = lval[CONVAL];
}
needtoken(":");
if (!const) {
gen_code(_JUMP, endlab = getlabel());
gen_code(_LABEL, falselab);
}
setstage(&before, &after);
if (plnge1(hier3, lval)) rvalue(lval);
else if (lval[CONEXP]) gen_code(_IMMED, lval[CONVAL]);
if (const>0) clearstage(before, 0); /* if true, delete 'else' expr */
else if (const<0) {
retconst = lval[CONEXP];
retval = lval[CONVAL];
}
if (!const) gen_code(_LABEL, endlab);
lval[CONEXP] = retconst;
lval[CONVAL] = retval;
lval[TYPEIND]=lval[TYPEPA]=lval[STAGE]=0;
return 0;
}
hier3(lval) int lval[]; {
return skim("||", _EQ0, 1, 0, hier4, lval);
}
hier4(lval) int lval[]; {
return skim("&&", _NE0, 0, 1, hier5, lval);
}
hier5(lval) int lval[]; {
return plnge("|", 0, hier6, lval);
}
hier6(lval) int lval[]; {
return plnge("^", 1, hier7, lval);
}
hier7(lval) int lval[]; {
return plnge("&", 2, hier8, lval);
}
hier8(lval) int lval[]; {
return plnge("== !=", 3, hier9, lval);
}
hier9(lval) int lval[]; {
return plnge("<= >= < >", 5, hier10, lval);
}
hier10(lval) int lval[]; {
return plnge(">> <<", 9, hier11, lval);
}
hier11(lval) int lval[]; {
return plnge("+ -", 11, hier12, lval);
}
hier12(lval) int lval[]; {
return plnge("* / %", 13, hier13, lval);
}
>>> CC32.C 6090
hier13(lval) int lval[]; {
int k;
char *ptr;
if(match("++")) { /* ++lval */
if(hier13(lval)==0) {
needlval();
return 0;
}
step(_INC, lval, 0);
return 0;
}
else if(match("--")) { /* --lval */
if(hier13(lval)==0) {
needlval();
return 0;
}
step(_DEC, lval, 0);
return 0;
}
else if (match("~")) { /* ~ */
if(hier13(lval)) rvalue(lval);
gen_code(_COM, 0);
lval[CONVAL] = ~ lval[CONVAL];
return (lval[STAGE]=0);
}
else if (match("!")) { /* ! */
if(hier13(lval)) rvalue(lval);
gen_code(_LNEG, 0);
lval[CONVAL] = ! lval[CONVAL];
return (lval[STAGE]=0);
}
else if (match("-")) { /* unary - */
if(hier13(lval)) rvalue(lval);
gen_code(_NEG, 0);
lval[CONVAL] = -lval[CONVAL];
return (lval[STAGE]=0);
}
else if(match("*")) { /* unary * */
if(hier13(lval)) rvalue(lval);
if(ptr=lval[SYMTBL]) lval[TYPEIND]=ptr[TYPE];
else lval[TYPEIND]=CINT;
lval[TYPEPA]=0; /* flag as not pointer or array */
lval[CONEXP]=0; /* flag as not constant */
lval[CONVAL]=1; /* omit rvalue() on func call */
lval[STAGE]=0;
return 1;
}
else if(match("sizeof(")) { /* sizeof() */
int *before, *start;
setstage(&before, &start);
k=hier13(lval);
clearstage(before, 0);
needtoken(")");
lval[CONEXP]=1;
if (lval[TYPEPA]) lval[CONVAL]=CINT>>2;
else lval[CONVAL]=lval[TYPEIND]>>2;
lval[TYPEPA]=lval[TYPEIND]=lval[SYMTBL]=0;
return 0;
}
else if(match("&")) { /* unary & */
if(hier13(lval)==0) {
error("illegal address");
return 0;
}
ptr=lval[SYMTBL];
lval[TYPEPA]=ptr[TYPE];
if(lval[TYPEIND]) return 0;
/* global & non-array */
gen_code(_OFFSET, ptr);
lval[TYPEIND]=ptr[TYPE];
return 0;
}
else {
k=hier14(lval);
if(match("++")) { /* lval++ */
if(k==0) {
needlval();
return 0;
}
step(_INC, lval, _DEC);
return 0;
}
else if(match("--")) { /* lval-- */
if(k==0) {
needlval();
return 0;
}
step(_DEC, lval, _INC);
return 0;
}
else return k;
}
}
hier14(lval) int *lval; {
int k, const, val, lval2[8];
char *ptr, *before, *start;
k=primary(lval);
ptr=lval[SYMTBL];
blanks();
if((ch=='[')|(ch=='(')) {
lval[REG2]=1; /* secondary register will be used */
while(1) {
if(match("[")) { /* [subscript] */
if(ptr==0) {
error("can't subscript");
junk();
needtoken("]");
return 0;
}
else if(ptr[IDENT]==POINTER) rvalue(lval);
else if(ptr[IDENT]!=ARRAY) {
error("can't subscript");
k=0;
}
setstage(&before, &start);
lval2[CONEXP]=0;
plnge2(0, 0, hier1, lval2, lval2); /* lval2 deadend */
needtoken("]");
if(lval2[CONEXP]) {
clearstage(before, 0);
if(lval2[CONVAL]) { /* only add if non-zero */
if(ptr[TYPE]==CINT) gen_code(_IMMED2, lval2[CONVAL]<<LBPW);
else gen_code(_IMMED2, lval2[CONVAL]);
gen_code(_ADD, 0);
}
}
else {
if(ptr[TYPE]==CINT) gen_code(_DBL, 0);
gen_code(_ADD, 0);
}
lval[TYPEPA]=0;
lval[TYPEIND]=ptr[TYPE];
k=1;
}
else if(match("(")) { /* function(...) */
if(ptr==0) callfunction(0);
else if(ptr[IDENT]!=FUNCTION) {
if(k && !lval[CONVAL]) rvalue(lval);
callfunction(0);
}
else callfunction(ptr);
k=lval[SYMTBL]=lval[CONEXP]=lval[CONVAL]=0;
}
else return k;
}
}
if(ptr==0) return k;
if(ptr[IDENT]==FUNCTION) {
gen_code(_OFFSET, ptr);
lval[SYMTBL]=0;
return 0;
}
return k;
}
primary(lval) int *lval; {
char *ptr, sname[NAMESIZE];
int k;
if(match("(")) { /* (expression,...) */
do k=hier1(lval); while(match(","));
needtoken(")");
return k;
}
putint(0, lval, 8<<LBPW); /* clear lval array */
if(symname(sname, YES)) {
if(ptr=findloc(sname)) {
#ifdef STGOTO
if(ptr[IDENT]==LABEL) {
experr();
return 0;
}
#endif
gen_code(_GSTK, ptr);
lval[SYMTBL]=ptr;
lval[TYPEIND]=ptr[TYPE];
if(ptr[IDENT]==POINTER) {
lval[TYPEIND]=CINT;
lval[TYPEPA]=ptr[TYPE];
}
if(ptr[IDENT]==ARRAY) {
lval[TYPEPA]=ptr[TYPE];
return 0;
}
else return 1;
}
if(ptr=findglb(sname))
if(ptr[IDENT]!=FUNCTION) {
lval[SYMTBL]=ptr;
lval[TYPEIND]=0;
if(ptr[IDENT]!=ARRAY) {
if(ptr[IDENT]==POINTER) lval[TYPEPA]=ptr[TYPE];
return 1;
}
gen_code(_OFFSET, ptr);
lval[TYPEIND]=lval[TYPEPA]=ptr[TYPE];
return 0;
}
ptr=addsym(sname, FUNCTION, CINT, 0, &glbptr, AUTOEXT);
lval[SYMTBL]=ptr;
lval[TYPEIND]=0;
return 0;
}
if(constant(lval)==0) experr();
return 0;
}
experr() {
error("invalid expression");
gen_code(_IMMED, 0);
junk();
}
callfunction(ptr) char *ptr; { /* symbol table entry or 0 */
int nargs, const, val;
nargs=0;
blanks(); /* already saw open paren */
while(streq(lptr,")")==0) {
if(endst()) break;
if(ptr) {
expression(&const, &val);
gen_code(_PUSH,0);
}
else {
gen_code(_PUSH,0);
expression(&const, &val);
gen_code(_SWAPSTK, 0); /* don't push addr */
}
nargs=nargs+BPW; /* count args*BPW */
if (match(",")==0) break;
}
needtoken(")");
if(streq(ptr+NAME, "CCARGC")==0) loadargc(nargs>>LBPW);
if(ptr) gen_code(_CALL, ptr);
else gen_code(_CALLSTK, 0);
gen_code(_MODSTK, csp+nargs);
}
>>> CC33.C 4768
/*
** true if val1 -> int pointer or int array and val2 not ptr or array
*/
dbltest(oper, val1,val2) int oper, val1[], val2[]; {
if((oper!=_ADD) && (oper!=_SUB)) return 0;
if(val1[TYPEPA]!=CINT) return 0;
if(val2[TYPEPA]) return 0;
return 1;
}
/*
** determine type of binary operation
*/
result(lval, lval2) int lval[], lval2[]; {
if((lval[TYPEPA]!=0)&(lval2[TYPEPA]!=0)) {
lval[TYPEPA]=0;
}
else if(lval2[TYPEPA]) {
lval[SYMTBL]=lval2[SYMTBL];
lval[TYPEIND]=lval2[TYPEIND];
lval[TYPEPA] =lval2[TYPEPA];
}
}
step(oper, lval, oper2) int oper, lval[], oper2; {
rvalue(lval);
gen_code(oper, lval[TYPEPA]>>2 ? lval[TYPEPA]>>2 : 1);
store(lval);
if(oper2) gen_code(oper2, lval[TYPEPA]>>2 ? lval[TYPEPA]>>2 : 1);
}
store(lval) int lval[]; {
char *sym;
if(lval[TYPEIND]) {
/* putstk */
if(lval[TYPEIND]==CCHAR) gen_code(_PCHAR, 0);
else gen_code(_PINT, 0);
}
else {
/* putmem */
sym = lval[SYMTBL];
if((sym[IDENT]!=POINTER)&(sym[TYPE]==CCHAR)) gen_code(_SCHAR, sym);
else gen_code(_SINT, sym);
}
}
rvalue(lval) int lval[]; {
char *sym;
if ((lval[SYMTBL]!=0)&(lval[TYPEIND]==0)) {
/* getmem */
sym = lval[SYMTBL];
if((sym[IDENT]!=POINTER)&(sym[TYPE]==CCHAR)) gen_code(_LCHAR, sym);
else gen_code(_LINT, sym);
}
else {
/* indirect */
if(lval[TYPEIND]==CCHAR) gen_code(_GCHAR, 0);
else gen_code(_GINT, 0);
}
}
test(label, parens) int label, parens; {
int lval[8];
int *before, *start;
if(parens) needtoken("(");
while(1) {
setstage(&before, &start);
if(hier1(lval)) rvalue(lval);
if(match(",")) clearstage(before, start);
else break;
}
if(parens) needtoken(")");
if(lval[CONEXP]) { /* constant expression */
clearstage(before, 0);
if(lval[CONVAL]) return;
gen_code(_JUMP, label);
return;
}
if(lval[STAGE]) { /* stage address of "oper 0" code */
switch(lval[OPER]) { /* operator code */
case _EQ:
case _ULE: zerojump(_EQ0, label, lval); break;
case _NE:
case _UGT: zerojump(_NE0, label, lval); break;
case _GT: zerojump(_GT0, label, lval); break;
case _GE: zerojump(_GE0, label, lval); break;
case _UGE: clearstage(lval[STAGE], 0); break;
case _LT: zerojump(_LT0, label, lval); break;
case _ULT: zerojump(_ULT0, label, lval); break;
case _LE: zerojump(_LE0, label, lval); break;
default: gen_code(_TESTJUMP, label); break;
}
}
else gen_code(_TESTJUMP, label);
clearstage(before, start);
}
constexpr(val) int *val; {
int const;
int *before, *start;
setstage(&before, &start);
expression(&const, val);
clearstage(before, 0); /* scratch generated code */
if(const==0) error("must be constant expression");
return const;
}
constant(lval) int lval[]; {
lval += CONEXP;
*lval=1; /* assume it will be a constant */
if (number(++lval)) gen_code(_IMMED, *lval);
else if (pstr(lval)) gen_code(_IMMED, *lval);
else if (qstr(lval)) {
*(lval-1)=0; /* nope, it's a string address */
gen_code(_STRING, *lval);
}
else return 0;
return 1;
}
number(val) int val[]; {
int k, minus;
k=minus=0;
while(1) {
if(match("+")) ;
else if(match("-")) minus=1;
else break;
}
if(isdigit(ch)==0) return 0;
if (ch=='0') {
while(ch == '0') inbyte();
if (toupper(ch)=='X') {
inbyte();
while(isxdigit(ch)) {
if (isdigit(ch)) k=k*16+(inbyte()-'0');
else k=k*16+10+(toupper(inbyte())-'A');
}
}
else while (ch>='0' && ch<='7') k=k*8+(inbyte()-'0');
}
else while (isdigit(ch)) k=k*10+(inbyte()-'0');
if (minus) k=(-k);
val[0]=k;
return 1;
}
pstr(val) int val[]; {
int k;
k=0;
if (match("'")==0) return 0;
while(ch!='\'') k=(k&255)*256 + (litchar()&255);
gch();
val[0]=k;
return 1;
}
qstr(val) int val[]; {
char c;
if (match(quote)==0) return 0;
val[0]=litptr;
while (ch!='"') {
if(ch==0) break;
stowlit(litchar(), 1);
}
gch();
litq[litptr++]=0;
return 1;
}
stowlit(value, size) int value, size; {
if((litptr+size) >= LITMAX) {
error("literal queue overflow");
abort(ERRCODE);
}
putint(value, litq+litptr, size);
litptr=litptr+size;
}
/*
** return current literal char & bump lptr
*/
litchar() {
int i, oct;
if((ch!='\\')|(nch==0)) return gch();
gch();
switch(ch) {
case 'n': gch(); return NEWLINE;
case 't': gch(); return 9; /* HT */
case 'b': gch(); return 8; /* BS */
case 'f': gch(); return 12; /* FF */
}
i=3; oct=0;
while(((i--)>0)&(ch>='0')&(ch<='7')) oct=(oct<<3)+gch()-'0';
if(i==2) return gch(); else return oct;
}
>>> CC4.C 420
/*
** Small-C Compiler Part 4
*/
#include <stdio.h>
#include "cc.def"
extern char
*cptr,
#ifdef DYNAMIC
*macn,
*symtab,
#else
macn[MACNSIZE],
symtab[SYMTBSZ],
#endif
#ifdef OPTIMIZE
optimize,
#endif
ssname[NAMESIZE];
extern int
#ifdef DYNAMIC
*stage,
#else
stage[STAGESIZE*2],
#endif
litlab, beglab, csp, output, oldseg,
*stagenext, *stagetail, *stagelast;
#include "cc41.c"
#include "cc42.c"
>>> CC41.C 4333
/*
** print all assembler info before any code is generated
** and ensure that the segments appear in the correct order.
*/
header() {
toseg(CODESEG);
ol("extrn __link: near");
ol("extrn __eq: near");
ol("extrn __ne: near");
ol("extrn __le: near");
ol("extrn __lt: near");
ol("extrn __ge: near");
ol("extrn __gt: near");
ol("extrn __ule: near");
ol("extrn __ult: near");
ol("extrn __uge: near");
ol("extrn __ugt: near");
ol("extrn __lneg: near");
ol("extrn __switch: near");
ol("dw 0"); /* ensure non-zero code pointers, retain word alignment */
toseg(DATASEG);
ol("dw 0"); /* ensure non-zero data pointers, retain word alignment */
}
/*
** print any assembler stuff needed at the end
*/
trailer() {
#ifndef LINK
if((beglab == 1)|(beglab > 9000)) {
/* implementation dependent trailer code goes here */
}
#else
cptr=STARTGLB;
while(cptr<ENDGLB) {
if(cptr[IDENT]==FUNCTION && cptr[CLASS]==AUTOEXT)
external(cptr+NAME,0,FUNCTION);
cptr+=SYMMAX;
}
#endif
toseg(NULL);
ol("END");
}
/*
** remember where we are in the queue in case we have to back up.
*/
setstage(before, start) int *before, *start; {
if((*before=stagenext)==0) stagenext=stage;
*start=stagenext;
}
/*
** put code into the queue.
*/
gen_code(func, value) int func, value; {
int size;
if (func==_PUSH) csp=csp-BPW;
else if(func==_POP) csp=csp+BPW;
else if(func==_MODSTK) {
size=value;
value-=csp;
csp=size;
}
if(stagenext==0) {
out_code(func,value);
return;
}
if(stagenext >= stagelast) {
error("staging buffer overflow");
return;
}
stagenext[0] = func;
stagenext[1] = value;
stagenext = nextq(stagenext);
}
nextq(qptr) int *qptr; {
qptr += 2;
if(qptr >= stagelast) qptr = stage;
return (qptr);
}
/*
** dump the contents of the queue.
** If start=0, throw away contents.
** If before!=0, don't dump queue yet.
*/
clearstage(before, start) int *before, *start; {
if(before) {stagenext = before; return;}
if(start) dumpstage();
stagenext = 0;
}
/*
** empty the queue.
*/
dumpstage() {
stagetail = stagenext;
stagenext = stage;
while(stagenext < stagetail) {
#ifdef OPTIMIZE
peephole();
#endif
out_code(stagenext[0], stagenext[1]);
stagenext = nextq(stagenext);
}
}
/*
** change to a new segment
** may be called with NULL, CODESEG, or DATASEG
*/
toseg(newseg) int newseg; {
if(oldseg==newseg) return;
if(oldseg==CODESEG) ol("CODE ENDS");
else if(oldseg==DATASEG) ol("DATA ENDS");
if(newseg==CODESEG) {
ol("CODE SEGMENT PUBLIC");
ol("ASSUME CS:CODE, SS:DATA, DS:DATA");
}
else if(newseg==DATASEG)
ol("DATA SEGMENT PUBLIC");
oldseg = newseg;
}
/*
** load # args before function call
*/
loadargc(val) int val; {
if(search("NOCCARGC", macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0) {
gen_code(_COUNT, val);
}
}
/*
** declare entry point
*/
public(size, ident) int size, ident;{
if (ident == FUNCTION) toseg(CODESEG);
else toseg(DATASEG);
#ifdef LINK
ot("PUBLIC ");
outname(ssname);
nl();
#endif
outname(ssname);
if (ident == FUNCTION) {col(); nl();}
}
/*
** declare external reference
*/
external(name, size, ident) char *name; int size, ident; {
#ifdef LINK
if (ident == FUNCTION) toseg(CODESEG);
else toseg(DATASEG);
ot("EXTRN ");
outname(name);
col();
outsize(size, ident);
nl();
#endif
}
/*
** swap primary and secondary registers
*/
outswap() {
ol("XCHG AX,BX");
}
/*
** output a label of specified number
*/
outlabel(lab) int lab; {
outstr("_");
outdec(lab);
}
/*
** output a jump to the specified label
*/
outjump(lab) int lab; {
ot("JMP ");
outlabel(lab);
nl();
}
/*
** output the size of the object pointed to.
*/
outsize(size, ident) int size, ident; {
if ((size==1)&(ident!=POINTER)&(ident!=FUNCTION)) {outstr("BYTE");}
else if (ident!=FUNCTION) {outstr("WORD");}
else {outstr("NEAR");};
}
/*
** output a call
*/
outcall(sname) char *sname; {
ot("CALL ");
outstr(sname);
nl();
}
/*
** test primary register against zero and jump if false
*/
zerojump(oper, label, lval) int oper, label, lval[]; {
clearstage(lval[7], 0); /* purge conventional code */
gen_code(oper, label);
}
/*
** point to following object(s)
*/
point() {
ol(" DW $+2");
}
>>> CC42.C 9580
#ifdef OPTIMIZE
/*
** Peephole Optimizer
*/
int
seq01[] = {_PUSH, _ANY, _POP, NULL},
seq02[] = {_GSTK, _IMMED2, _ADD, _GINT, NULL},
seq03[] = {_GSTK, _IMMED2, _ADD, _GCHAR, NULL},
seq04[] = {_OFFSET, _IMMED2, _ADD, _GINT, NULL},
seq05[] = {_OFFSET, _IMMED2, _ADD, _GCHAR, NULL},
seq08[] = {_GSTK, _GCHAR, NULL},
seq09[] = {_GSTK, _GINT, NULL},
seq10[] = {_MOVE, _IMMED, _SUB, NULL},
seq11[] = {_INC, _PINT, _DEC, NULL},
seq12[] = {_DEC, _PINT, _INC, NULL},
seq13[] = {_INC, _PCHAR, _DEC, NULL},
seq14[] = {_DEC, _PCHAR, _INC, NULL},
seq15[] = {_INC, _SINT, _DEC, NULL},
seq16[] = {_INC, _SCHAR, _DEC, NULL},
seq17[] = {_DEC, _SINT, _INC, NULL},
seq18[] = {_DEC, _SCHAR, _INC, NULL},
seq19[] = {_IMMED2, _ADD, NULL};
peephole() {
while(optimize) {
if(peep(seq01)) { /* _PUSH_ANY_POP --> _MOVE_ANY */
stagenext[4] = stagenext[2];
stagenext[5] = stagenext[3];
stagenext[2] = _MOVE;
stagenext += 2;
}
else if(peep(seq02)) { /* _GSTK_IMMED2_ADD_GINT --> _GLIO */
stagenext[6] = _GLIO;
stagenext[7] = getint(stagenext[1]+OFFSET, OFFSIZE) + stagenext[3];
stagenext += 6;
}
else if(peep(seq03)) { /* _GSTK_IMMED2_ADD_GCHAR --> _GLCO */
stagenext[6] = _GLCO;
stagenext[7] = getint(stagenext[1]+OFFSET, OFFSIZE) + stagenext[3];
stagenext += 6;
}
else if(peep(seq04)) { /* _OFFSET_IMMED2_ADD_GINT --> _GGIO */
stagenext[4] = _GGIO1;
stagenext[5] = stagenext[1];
stagenext[6] = _GGIO2;
stagenext[7] = stagenext[3];
stagenext += 4;
}
else if(peep(seq05)) { /* _OFFSET_IMMED2_ADD_GCHAR --> _GGCO */
stagenext[4] = _GGCO1;
stagenext[5] = stagenext[1];
stagenext[6] = _GGCO2;
stagenext[7] = stagenext[3];
stagenext += 4;
}
else if(peep(seq08)) /* _GSTK_GCHAR --> _FCHAR */
merge(_FCHAR);
else if(peep(seq09)) /* _GSTK_GINT --> _FINT */
merge(_FINT);
else if(peep(seq10)) { /* _MOVE_IMMED_SUB --> _SUBI */
stagenext[4] = _SUBI;
stagenext[5] = stagenext[3];
stagenext += 4;
}
else if(peep(seq11)) { /* _INC_PINT_DEC --> _INT_I */
stagenext[4] = _INT_I;
stagenext += 4;
}
else if(peep(seq12)) { /* _DEC_PINT_INC --> _INT_D */
stagenext[4] = _INT_D;
stagenext += 4;
}
else if(peep(seq13)) { /* _INC_PCHAR_DEC --> _CHAR_I */
stagenext[4] = _CHAR_I;
stagenext += 4;
}
else if(peep(seq14)) { /* _DEC_PCHAR_INC --> _CHAR_D */
stagenext[4] = _CHAR_D;
stagenext += 4;
}
else if(peep(seq15) ||
peep(seq16)) { /* _INC_Sxxx_DEC --> _XXX_I1 */
stagenext[2] = _XXX_I1;
stagenext[4] = _XXX_X2;
stagenext += 2;
}
else if(peep(seq17) ||
peep(seq18)) { /* _DEC_Sxxx_INC --> _XXX_D1 */
stagenext[2] = _XXX_D1;
stagenext[4] = _XXX_X2;
stagenext += 2;
}
else if(peep(seq19)) /* _IMMED2_ADD --> _ADDI */
merge(_ADDI);
else break;
}
}
/*
** peep into the staging buffer for a match
*/
peep(seq) int *seq; {
int *next;
next = stagenext;
while(*seq) {
if(next >= stagetail || (*seq != _ANY && *seq != *next))
return (NO);
next += 2;
++seq;
}
return (YES);
}
/*
** Merge top two p-codes into one with code "func" and the top value.
*/
merge(func) int func; {
stagenext[2] = func;
stagenext[3] = stagenext[1];
stagenext += 2;
}
#endif
/*
** take code out of the queue.
*/
out_code(func, value) int func, value; {
char *str;
str = value;
switch(func) {
case _LABEL: {outlabel(value); col(); nl(); break;}
case _RLAB: {outlabel(value); break;}
case _GCHAR: {ol("MOV BX,AX"); ol("MOV AL,[BX]"); ol("CBW"); break;}
case _GINT: {ol("MOV BX,AX"); ol("MOV AX,[BX]"); break;}
case _LINT: {ot("MOV AX,"); outname(str+NAME); nl(); break;}
case _LCHAR: {ot("MOV AL,"); outname(str+NAME); nl(); ol("CBW"); break;}
case _GSTK: {ot("LEA AX,"); outdec(getint(str+OFFSET, OFFSIZE));
outstr("[BP]"); nl(); break;}
case _SCHAR: {ot("MOV "); outname(str+NAME); outstr(",AL"); nl(); break;}
case _SINT: {ot("MOV "); outname(str+NAME); outstr(",AX"); nl(); break;}
case _PINT: {ol("MOV [BX],AX"); break;}
case _PCHAR: {ol("MOV [BX],AL"); break;}
case _MOVE: {ol("MOV BX,AX"); break;}
case _SWAP: {outswap(); break;}
case _OFFSET:{ot("MOV AX,OFFSET "); outname(str+NAME); nl(); break;}
case _STRING:{ot("MOV AX,OFFSET "); outlabel(litlab); outstr("+");
outdec(value); nl(); break;}
case _IMMED: {
if(value) {ot("MOV AX,"); outdec(value);}
else ot("XOR AX,AX");
nl();
break;
}
case _IMMED2: {
if(value) {ot("MOV BX,"); outdec(value);}
else ot("XOR BX,BX");
nl();
break;
}
case _COUNT: {
if(value) {ot("MOV CL,"); outdec(value);}
else ot("XOR CL,CL");
nl();
break;
}
case _PUSH: {ol("PUSH AX"); break;}
case _POP: {ol("POP BX"); break;}
case _SWAPSTK: {ol("POP BX"); ol("XCHG AX,BX"); ol("PUSH BX"); break;}
case _SW: {outcall("__SWITCH"); break;}
case _CALL: {ot("CALL "); outname(str+NAME); nl(); break;}
case _FUNC: {ol("PUSH BP"); ol("MOV BP,SP"); break;}
case _RET: {ol("POP BP"); ol("RET"); break;}
case _CALLSTK: {ol("CALL AX"); break;}
case _JUMP: {outjump(value); break;}
case _TESTJUMP:{ol("OR AX,AX"); ol("JNZ $+5"); outjump(value); break;}
case _DB: {ot(" DB "); break;}
case _DBZERO: {ot(" DB "); outdec(value); outstr(" DUP(0)"); nl(); break;}
case _DEFBYTE: {ot(" DB "); outdec(value); nl(); break;}
case _DW: {ot(" DW "); break;}
case _DWZERO: {ot(" DW "); outdec(value); outstr(" DUP(0)"); nl(); break;}
case _DEFWORD: {ot(" DW "); outdec(value); nl(); break;}
case _DEFLABEL:{ot(" DW "); outlabel(value); nl(); break;}
case _MODSTK: {
if(value) {ot("ADD SP,"); outdec(value); nl();}
break;
}
case _DBL: {ol("ADD AX,AX"); break;}
case _DBL2: {ol("ADD BX,BX"); break;}
case _ADD: {ol("ADD AX,BX"); break;}
case _SUB: {outswap(); ol("SUB AX,BX"); break;}
case _MULT: {ol("IMUL BX"); break;}
case _DIV: {outswap(); ol("CWD"); ol("IDIV BX"); break;}
case _MOD: {outswap(); ol("CWD"); ol("IDIV BX"); ol("MOV AX,DX"); break;}
case _OR: {ol("OR AX,BX"); break;}
case _XOR: {ol("XOR AX,BX"); break;}
case _AND: {ol("AND AX,BX"); break;}
case _LNEG: {outcall("__LNEG"); break;}
case _ASR: {ol("MOV CX,AX"); ol("MOV AX,BX"); ol("SAR AX,CL"); break;}
case _ASL: {ol("MOV CX,AX"); ol("MOV AX,BX"); ol("SAL AX,CL"); break;}
case _NEG: {ol("NEG AX"); break;}
case _COM: {ol("NOT AX"); break;}
case _INC: {while(1) {ol("INC AX"); if(--value < 1) break;} break;}
case _DEC: {while(1) {ol("DEC AX"); if(--value < 1) break;} break;}
case _EQ: {outcall("__EQ"); break;}
case _EQ0: {ol("OR AX,AX"); ol("JZ $+5"); outjump(value); break;}
case _NE: {outcall("__NE"); break;}
case _NE0: {ol("OR AX,AX"); ol("JNZ $+5"); outjump(value); break;}
case _LT: {outcall("__LT"); break;}
case _LT0: {ol("OR AX,AX"); ol("JL $+5"); outjump(value); break;}
case _LE: {outcall("__LE"); break;}
case _LE0: {ol("OR AX,AX"); ol("JLE $+5"); outjump(value); break;}
case _GT: {outcall("__GT"); break;}
case _GT0: {ol("OR AX,AX"); ol("JG $+5"); outjump(value); break;}
case _GE: {outcall("__GE"); break;}
case _GE0: {ol("OR AX,AX"); ol("JGE $+5"); outjump(value); break;}
case _ULT: {outcall("__ULT"); break;}
case _ULT0: {outjump(value); break;}
case _ULE: {outcall("__ULE"); break;}
case _UGT: {outcall("__UGT"); break;}
case _UGE: {outcall("__UGE"); break;}
case _GLIO: {
ot("LEA BX,"); outdec(value); outstr("[BP]"); nl();
ol("MOV AX,[BX]");
break;
}
case _GLCO: {
ot("LEA BX,"); outdec(value); outstr("[BP]"); nl();
ol("MOV AL,[BX]");
ol("CBW");
break;
}
case _GGIO1: {ot("MOV BX,OFFSET "); outname(str+NAME); break;}
case _GGIO2: {
if(value >= 0) outstr("+"); outdec(value); nl();
ol("MOV AX,[BX]");
break;
}
case _GGCO1: {ot("MOV BX,OFFSET "); outname(str+NAME); break;}
case _GGCO2: {
if(value >= 0) outstr("+"); outdec(value); nl();
ol("MOV AL,[BX]");
ol("CBW");
break;
}
case _INT_I: {ot("ADD WORD PTR [BX],"); outdec(value); nl(); break;}
case _INT_D: {ot("SUB WORD PTR [BX],"); outdec(value); nl(); break;}
case _CHAR_I:{ot("ADD BYTE PTR [BX],"); outdec(value); nl(); break;}
case _CHAR_D:{ot("SUB BYTE PTR [BX],"); outdec(value); nl(); break;}
case _XXX_I1:{ot("ADD "); outname(str+NAME); break;}
case _XXX_D1:{ot("SUB "); outname(str+NAME); break;}
case _XXX_X2:{outstr(","); outdec(value); nl(); break;}
case _FINT: {
ot("LEA BX,"); outdec(getint(str+OFFSET, OFFSIZE)); outstr("[BP]"); nl();
ol("MOV AX,[BX]");
break;
}
case _FCHAR: {
ot("LEA BX,"); outdec(getint(str+OFFSET, OFFSIZE)); outstr("[BP]"); nl();
ol("MOV AL,[BX]");
ol("CBW");
break;
}
case _ADDI: {ot("ADD AX,"); outdec(value); nl(); break;}
case _SUBI: {ot("SUB AX,"); outdec(value); nl(); break;}
default: {error("bad pcode"); break;}
}
}